from qgis.PyQt.QtWidgets import (QDialog, QVBoxLayout, QLabel, QLineEdit, 
                                QPushButton, QAction, QMessageBox)
from qgis.PyQt.QtGui import QIcon, QColor
from qgis.core import (QgsProject, QgsPointXY, QgsCoordinateTransform, 
                      QgsCoordinateReferenceSystem, QgsFeature, QgsGeometry,
                      QgsMapLayerProxyModel, QgsWkbTypes)
from qgis.gui import QgsMapLayerComboBox,QgsAttributeDialog,QgsRubberBand
from PyQt5.QtCore import Qt
import os

class CreateXY:
    def __init__(self, iface, parent=None):
        self.iface = iface
        self.dialog = None
    
    def CreateXY_initGui(self):
      self.action = QAction(QIcon(os.path.join(os.path.dirname(__file__), 'icons/xy.png')), "xy创建点", self.iface.mainWindow())
      
      self.action.triggered.connect(self.CreateXY_run)
      self.digitize_toolbar = self.iface.digitizeToolBar()
      if self.digitize_toolbar:
          self.digitize_toolbar.addAction(self.action)

    def CreateXY_unload(self):
        if self.digitize_toolbar:
            self.digitize_toolbar.removeAction(self.action)
            del self.action
        
        # 关闭对话框
        if self.dialog:
            self.dialog.close()
    
    def CreateXY_run(self):
        if not self.dialog:
            self.dialog = PointCreatorDialog(self.iface, self.iface.mainWindow())
        self.dialog.show()
        self.dialog.raise_()
        self.dialog.activateWindow()


class PointCreatorDialog(QDialog):
    def __init__(self, iface, parent=None):
        super().__init__(parent)
        self.iface = iface
        self.setWindowTitle("创建点要素")
        self.setMinimumWidth(300)

        layout = QVBoxLayout()

        # 坐标系提示
        self.crs = QgsProject.instance().crs()
        layout.addWidget(QLabel("当前工程指定坐标系为：" + self.crs.authid()))

        # 点图层选择
        layout.addWidget(QLabel("选择点图层:"))
        self.layer_combo = QgsMapLayerComboBox()
        self.layer_combo.setFilters(QgsMapLayerProxyModel.PointLayer)
        layout.addWidget(self.layer_combo)

        # X坐标输入
        layout.addWidget(QLabel("X 坐标:"))
        self.x_input = QLineEdit()
        self.x_input.setPlaceholderText("请输入X坐标")
        layout.addWidget(self.x_input)

        # Y坐标输入
        layout.addWidget(QLabel("Y 坐标:"))
        self.y_input = QLineEdit()
        self.y_input.setPlaceholderText("请输入Y坐标")
        layout.addWidget(self.y_input)

        # 创建按钮
        self.create_button = QPushButton("创建点要素")
        self.create_button.setStyleSheet("background-color: #4CAF50; color: white;")
        self.create_button.clicked.connect(self.create_point)
        layout.addWidget(self.create_button)

        self.setLayout(layout)

    def transform_coordinates(self, x, y, src_crs, dest_crs):
        try:
            xform = QgsCoordinateTransform(src_crs, dest_crs, QgsProject.instance())
            return xform.transform(QgsPointXY(x, y))
        except Exception as e:
            QMessageBox.warning(self, "坐标转换错误", f"无法转换坐标: {str(e)}")
            return None

    def create_point(self):
        layer = self.layer_combo.currentLayer()
        if not layer:
            QMessageBox.warning(self, "警告", "请先选择一个点图层!")
            return

        if not layer.isValid():
            QMessageBox.warning(self, "图层无效", "所选图层无效，请选择有效图层。")
            return

        try:
            x = float(self.x_input.text())
            y = float(self.y_input.text())
        except ValueError:
            QMessageBox.warning(self, "输入错误", "请输入有效的数字坐标!")
            return

        crs_src = QgsCoordinateReferenceSystem(self.crs.authid())
        crs_dest = layer.crs()
        point = QgsPointXY(x, y)

        if crs_src != crs_dest:
            point = self.transform_coordinates(x, y, crs_src, crs_dest)
            if point is None:
                return

        was_editing = layer.isEditable()
        if not was_editing:
            layer.startEditing()

        feature = QgsFeature(layer.fields())
        feature.setGeometry(QgsGeometry.fromPointXY(point))
        #
        # 获取地图画布
        canvas = self.iface.mapCanvas()

        # 将画布中心移动到新添加的点的位置
        canvas.setCenter(point)
        self.show_crosshair_at_point(canvas, point, 5)
        canvas.refresh()
        # 弹出属性编辑对话框
        dialog = QgsAttributeDialog(layer, feature, False, self)
        dialog.setMode(1)
        dialog.setWindowTitle("编辑点要素属性")

        if dialog.exec_():
            # 用户点击了 OK，保存要素
            # if layer.addFeature(feature):
            if not was_editing:
                layer.commitChanges()
                canvas.refresh()
            reply = QMessageBox.information(self, "成功", "点要素已成功创建并保存！", QMessageBox.Ok)
            if reply == QMessageBox.Ok:
                self.clear_crosshair()
        else:
            # 用户取消了属性输入
            if not was_editing:
                layer.rollBack()
            reply = QMessageBox.information(self, "取消", "取消创建点要素。", QMessageBox.Ok)
            if reply == QMessageBox.Ok:
                self.clear_crosshair()
    def closeEvent(self, event):
        self.x_input.clear()
        self.y_input.clear()
    def show_crosshair_at_point(self, canvas, point, size=0.0005):
        self.clear_crosshair()

        # 创建新的十字线并保存为成员变量
        self.crosshair_horizontal = QgsRubberBand(canvas, QgsWkbTypes.LineGeometry)
        self.crosshair_vertical = QgsRubberBand(canvas, QgsWkbTypes.LineGeometry)

        # 设置样式
        for line in [self.crosshair_horizontal, self.crosshair_vertical]:
            line.setColor(QColor(255, 0, 0))  # 红色
            line.setWidth(2)
            line.setLineStyle(Qt.SolidLine)

        # 设置十字的范围
        x, y = point.x(), point.y()
        self.crosshair_horizontal.addPoint(QgsPointXY(x - size, y))
        self.crosshair_horizontal.addPoint(QgsPointXY(x + size, y))
        self.crosshair_vertical.addPoint(QgsPointXY(x, y - size))
        self.crosshair_vertical.addPoint(QgsPointXY(x, y + size))
    def clear_crosshair(self):
        if hasattr(self, 'crosshair_horizontal') and self.crosshair_horizontal:
            self.crosshair_horizontal.reset(QgsWkbTypes.LineGeometry)
            self.crosshair_horizontal = None
        if hasattr(self, 'crosshair_vertical') and self.crosshair_vertical:
            self.crosshair_vertical.reset(QgsWkbTypes.LineGeometry)
            self.crosshair_vertical = None